package com.yixing.tech.common.service;

import com.alibaba.fastjson.JSONObject;
import com.yixing.tech.common.base.BusinessException;
import com.yixing.tech.common.enums.ErrCode;
import com.yixing.tech.common.security.context.UserContext;
import com.yixing.tech.common.utils.CommonConstant;
import com.yixing.tech.common.utils.CommonSpringUtils;
import com.yixing.tech.common.utils.CommonUtil;
import com.yixing.tech.common.vo.s3.DepartmentVO;
import com.yixing.tech.common.vo.s3.UserVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class CommonService {

    @Value("${official-tenant-id}")
    private String officialTenantId;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 获取当前请求的 HttpServletRequest
     */
    public static HttpServletRequest getRequest() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            return null;
        }
        return requestAttributes.getRequest();
    }

    /**
     * 获取当前请求的 HttpServletResponse
     */
    public static HttpServletResponse getResponse() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            return null;
        }
        return requestAttributes.getResponse();
    }

    /**
     * 获取用户 IP 地址
     */
    public static String getIp() {
        HttpServletRequest request = getRequest();
        if (request == null) {
            return null;
        }
        String ip = request.getHeader(CommonConstant.HEADERS_IP);
        if (CommonUtil.stringIsBlank(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    /**
     * 根据 token 获取用户信息
     */
    public static UserVO getApiUser(String apiToken) throws BusinessException {
        String json = CommonSpringUtils.getStringRedisTemplate().opsForValue().get(CommonConstant.USERTOKEN + apiToken);
        if (ObjectUtils.isEmpty(json)) {
            throw new BusinessException(ErrCode.TOKEN_INVALID);
        }
        UserVO user = JSONObject.parseObject(json, UserVO.class);
        CommonSpringUtils.getStringRedisTemplate().expire(CommonConstant.USERTOKEN + apiToken,
                CommonConstant.REDIS_APIUSER_EXPIRE, TimeUnit.SECONDS);
        return user;
    }

    /**
     * 获取当前用户信息，兼容老方法
     */
    public static UserVO getApiUser() throws BusinessException {
        UserVO userVO = new UserVO();
        userVO.setId(UserContext.getUserId());
        return userVO;
    }

    /**
     * 刷新用户信息
     */
    public static void reflashApiUser(UserVO obj, String apiToken, String client) throws BusinessException {
        String oldToken = CommonSpringUtils.getStringRedisTemplate().opsForValue().get(CommonConstant.REDIS_USERID_PREFIX + client + ":" + obj.getId());
        if (!ObjectUtils.isEmpty(oldToken)) {
            CommonSpringUtils.getStringRedisTemplate().delete(CommonConstant.USERTOKEN + oldToken);
        }
        String json = JSONObject.toJSONString(obj);
        CommonSpringUtils.getStringRedisTemplate().opsForValue().set(CommonConstant.USERTOKEN + apiToken,
                json, CommonConstant.REDIS_APIUSER_EXPIRE, TimeUnit.SECONDS);
        CommonSpringUtils.getStringRedisTemplate().opsForValue().set(CommonConstant.REDIS_USERID_PREFIX + client + ":" + obj.getId(),
                apiToken, CommonConstant.REDIS_USERID_EXPIRE, TimeUnit.SECONDS);
    }

    /**
     * 创建 Token
     */
    public static String createToken() {
        return CommonUtil.createUuid();
    }

    /**
     * 获取 API Token
     */
    public static String getApiToken() throws BusinessException {
        HttpServletRequest request = getRequest();
        if (request == null) {
            throw new BusinessException(ErrCode.TOKEN_INVALID);
        }
        String value = request.getHeader(CommonConstant.HEADERS_X_USER);
        if (CommonUtil.stringIsBlank(value)) {
            throw new BusinessException(ErrCode.TOKEN_INVALID);
        }
        return value;
    }

    /**
     * 填充创建用户信息到 VO 对象
     */
    public static void fillCreateUser(com.yixing.tech.common.base.BaseVO vo) throws BusinessException {
        UserVO userVO = getApiUser();
        if (userVO != null) {
            vo.setCreateId(userVO.getId());
            vo.setCreateName(userVO.getName());
            vo.setTenantId(userVO.getTenantId());
            DepartmentVO departmentVO = userVO.getDepartment();
            if (departmentVO != null)
                vo.setDepartmentId(departmentVO.getId());
        }
    }

    /**
     * 填充创建用户信息到 Map 对象
     */
    public static void fillCreateUser(Map vo) throws BusinessException {
        UserVO userVO = getApiUser();
        if (userVO != null) {
            vo.put("createId", userVO.getId());
            vo.put("createName", userVO.getName());
            vo.put("tenantId", userVO.getTenantId());
            DepartmentVO departmentVO = userVO.getDepartment();
            if (departmentVO != null)
                vo.put("departmentId", departmentVO.getId());
            Date date = new Date();
            vo.put("createTime", date);
            vo.put("updateTime", date);
        }
    }

    /**
     * 填充更新用户信息到 VO 对象
     */
    public static void fillUpdateUser(com.yixing.tech.common.base.BaseVO vo) throws BusinessException {
        UserVO userVO = getApiUser();
        if (userVO != null) {
            vo.setUpdateId(userVO.getId());
            vo.setUpdateName(userVO.getName());
            Date date = new Date();
            vo.setUpdateTime(date);
        }
    }

    /**
     * 填充更新用户信息到 Map 对象
     */
    public static void fillUpdateUser(Map vo) throws BusinessException {
        UserVO userVO = getApiUser();
        if (userVO != null) {
            vo.put("updateId", userVO.getId());
            vo.put("updateName", userVO.getName());
            Date date = new Date();
            vo.put("updateTime", date);
        }
    }

    /**
     * 获取租户 ID
     */
    public static String getTenantId() throws BusinessException {
        UserVO userVO = getApiUser();
        return userVO.getTenantId();
    }
}
